package com.feather.tenia;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.feather.common.db.Connector;
import com.feather.common.log.LogProvider;
import com.feather.common.log.Logger;
import com.feather.tenia.adapter.JdbcPropertyImpl;

/**
 * 
 * @author flogyin
 */
public class TeniaFactory {
	private static HashMap<String, String>	_FINDER_MAP	= new HashMap<String, String>();
	static {
		// can add others DB product
		registerTeniaFinder("Oracle", "com.feather.tenia.oracle.OracleTeniaFinder");
		registerTeniaFinder("MySQL", "com.feather.tenia.mysql.MysqlTeniaFinder");
		registerTeniaFinder("Microsoft SQL Server", "com.feather.tenia.mssqlserver.SqlserverTeniaFinder");
	}

	private static Tenia					_DEFAULT;
	private static Map<String, Tenia>		_TENIA_MAP	= new ConcurrentHashMap<String, Tenia>();

	public static JdbcProperty createJdbcProperty(Connector connector) {
		return JdbcPropertyImpl.instance(connector);
	}

	public static Tenia get(String caption) {
		return caption != null && caption.length() > 0 ? _TENIA_MAP.get(caption) : _DEFAULT;
	}

	public static Tenia get() {
		return _DEFAULT;
	}

	public static void setDefault(Tenia tenia) {
		_DEFAULT = tenia;
	}

	public static void put(Tenia tenia) {
		put(tenia, false);
	}

	public static void put(Tenia tenia, boolean isDefault) {
		String caption = tenia.getCaption();
		boolean emptyCaption = caption == null || caption.length() == 0;
		isDefault = isDefault || emptyCaption;
		if (isDefault) {
			_DEFAULT = tenia;
		}
		if (!emptyCaption)
			_TENIA_MAP.put(caption, tenia);
	}

	public static Tenia create(Connector connector) {
		return create(null, connector, true);
	}

	public static Tenia create(String caption, Connector connector) {
		return create(caption, connector, false);
	}

	public static Tenia create(String caption, Connector connector, boolean isDefault) {
		JdbcProperty jdbcProperty = JdbcPropertyImpl.instance(connector);

		String dbProductName = jdbcProperty.getDatabaseProductName();

		Logger productLog = LogProvider.CURRENT[0].createPrinter();
		productLog.setSource(TeniaFactory.class);
		productLog.setMethod("createTenia");
		productLog.setMessage("for product: " + dbProductName);
		productLog.print();

		String finderClassName = _FINDER_MAP.get(dbProductName);
		if (finderClassName != null) {
			Logger finderLog = LogProvider.CURRENT[0].createPrinter();
			finderLog.setSource(TeniaFactory.class);
			finderLog.setMethod("createTenia");
			finderLog.setMessage("found: " + finderClassName);
			finderLog.print();

			TeniaFinder finder = null;
			try {
				@SuppressWarnings("rawtypes")
				Class finderClass = Class.forName(finderClassName);
				finder = (TeniaFinder) finderClass.newInstance();
			} catch (Exception ex) {
				throw new RuntimeException(ex);
			}

			if (finder != null) {
				Tenia tenia = finder.getTenia(connector, jdbcProperty);
				if (tenia != null) {
					Logger teniaLog = LogProvider.CURRENT[0].createPrinter();
					teniaLog.setSource(TeniaFactory.class);
					teniaLog.setMethod("createTenia");
					teniaLog.setMessage("found: " + tenia.getClass().getName());
					teniaLog.print();

					tenia.setCaption(caption);
					put(tenia, isDefault);
					return tenia;
				}
			}
		}
		throw new RuntimeException("Not found implements for Tenia.");
	}

	public static void registerTeniaFinder(String dbName, String teniaFinderClass) {
		_FINDER_MAP.put(dbName, teniaFinderClass);
	}

	public static void removeTeniaFinder(String dbName) {
		_FINDER_MAP.remove(dbName);
	}

	public static void clearTeniaFinder() {
		_FINDER_MAP.clear();
	}
}
